/*** 
 * @_______________#########_______________________ 
 * @______________############_____________________ 
 * @______________#############____________________ 
 * @_____________##__###########___________________ 
 * @____________###__######_#####__________________ 
 * @____________###_#######___####_________________ 
 * @___________###__##########_####________________ 
 * @__________####__###########_####_______________ 
 * @________#####___###########__#####_____________ 
 * @_______######___###_########___#####___________ 
 * @_______#####___###___########___######_________ 
 * @______######___###__###########___######_______ 
 * @_____######___####_##############__######______ 
 * @____#######__#####################_#######_____ 
 * @____#######__##############################____ 
 * @___#######__######_#################_#######___ 
 * @___#######__######_######_#########___######___ 
 * @___#######____##__######___######_____######___ 
 * @___#######________######____#####_____#####____ 
 * @____######________#####_____#####_____####_____ 
 * @_____#####________####______#####_____###______ 
 * @______#####______;###________###______#________ 
 * @________##_______####________####______________ 
 * @
 * @Author: ipk518 18163976442@163.com
 * @Date: 2024-12-10 10:19:11
 * @LastEditors: ipk518 121206530@qq.com
 * @LastEditTime: 2025-08-14 19:46:53
 * @FilePath: /etws-sxk2307/src/Devices/Qsfp.cpp
 * @Description: 
 * @************佛祖保佑************
 * @Copyright (c) 2024 by etws@quyujiang, All Rights Reserved. 
 */
#include "commHeader.h"
// #include "I2c.h"
#include "Qsfp.h"

#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>


int m_qsfp_4x_fd = -1;
int m_qsfp_12x_fd = -1;

uint8_t m_qsfp_4x_upper[QSFP_PAGENUM_4X][QSFP_PAGEUPPER];
uint8_t m_qsfp_12x_tx_upper[QSFP_PAGENUM_12X][QSFP_PAGEUPPER];
uint8_t m_qsfp_12x_rx_upper[QSFP_PAGENUM_12X][QSFP_PAGEUPPER];


/**************************************************************************************** */
#define TEMP_MIN -10    // 有效温度范围下限  
#define TEMP_MAX 85     // 有效温度范围上限  
#define TEMP_OFFSET 128 // 0℃在16位补码中的偏移  
#define VOLTAGE_MIN 0   // 电压范围下限 (0V)  
#define VOLTAGE_MAX 65535 // 电压范围上限 (65535)  
#define LSB_VOLTAGE 0.0001 // 100μV对应的伏特值  
#define VOLTAGE_PRECISION 0.03 // 电压精度±3%  

#define BIAS_CURRENT_LSB 0.000002 // 2μA对应的安培值  
#define BIAS_CURRENT_MAX 131.0 // 偏置电流最大值 (mA)  
#define BIAS_CURRENT_PRECISION 0.1 // 偏置电流精度 ±10%  

#define RX_POWER_LSB 0.0001 // 0.1μW对应的瓦特值  
#define RX_POWER_MAX 6.5535 // 接收光功率最大值 (mW)  
#define RX_POWER_PRECISION 3.0 // 接收功率精度 ±3 dB  

int16_t convertTemperature(uint16_t rawTemp) {  
    // 将16位无符号整数转换为有符号整数  
    // 温度值的增量为1/256摄氏度，所以需要进行转换  
    return (int16_t)(rawTemp - TEMP_OFFSET) * (1.0 / 256);  
}  

// 电压转换函数  
double convertVoltage(uint16_t rawVoltage) {  
    return rawVoltage * LSB_VOLTAGE;  
}  

// 温度有效性检查  
void checkTemperatureValidity(int16_t temperature) {  
    if (temperature < TEMP_MIN || temperature > TEMP_MAX) {  
        printf("警告：温度 (%d℃) 超出有效范围 (%d℃ 到 %d℃)！\n", temperature, TEMP_MIN, TEMP_MAX);  
    } else {  
        printf("温度 (%d℃) 在有效范围内。\n", temperature);  
    }  
}  

// 电压有效性检查  
void checkVoltageValidity(double voltage) {  
    double minValid = voltage * (1 - VOLTAGE_PRECISION);  
    double maxValid = voltage * (1 + VOLTAGE_PRECISION);  
    printf("电压: %.2f V\n", voltage);  
    printf("电压有效范围: [%.2f V, %.2f V]\n", minValid, maxValid);  
}  

// 偏置电流转换函数  
double convertBiasCurrent(uint16_t rawCurrent) {  
    return rawCurrent * BIAS_CURRENT_LSB * 1000; // 转换为mA  
}  

// 接收功率转换函数  
double convertPower(uint16_t rawPower) {  
    return rawPower * RX_POWER_LSB; // 转换为mW  
}  

// 偏置电流有效性检查  
void checkBiasCurrentValidity(double current) {  
    double minValid = current * (1 - BIAS_CURRENT_PRECISION / 100);  
    double maxValid = current * (1 + BIAS_CURRENT_PRECISION / 100);  
    printf("偏置电流: %.6f mA\n", current);  
    printf("偏置电流有效范围: [%.6f mA, %.6f mA]\n", minValid, maxValid);  
}  

// 接收功率有效性检查  
void checkPowerValidity(double power) {  
    double minDB = power - RX_POWER_PRECISION; // dBm单位  
    double maxDB = power + RX_POWER_PRECISION;  
    printf("功率: %.6f mW\n", power);  
    printf("接收功率有效范围: [%.6f dBm, %.6f dBm]\n", minDB, maxDB);  
}  

//温度、电压监控换算
int printMonitor(uint16_t rawTemperature,uint16_t rawVoltage) {  

    // 输入温度值  
    // qlog_i("请输入模块的原始温度值 (16位无符号整数)：");  
    // scanf("%hu", &rawTemperature);  
    int16_t temperature = convertTemperature(rawTemperature);  
    
    printf("转换后的温度为: %.2f℃\n", (float)temperature);  
    checkTemperatureValidity(temperature);  

    // 输入电压值  
    // qlog_i("请输入模块的原始电压值 (16位无符号整数)：");  
    // scanf("%hu", &rawVoltage);  
    double voltage = convertVoltage(rawVoltage);  
    
    checkVoltageValidity(voltage);  

    return 0;  
}  


/*********************************************************************************************************************** */


static int qsfp_init(const char *devName)
{
    int fd = 0;

    //打开IIC总线设备节点
    // fd = open(reinterpret_cast<const char*>(dev_path), O_RDWR);
    fd = open(devName, O_RDWR);
    return fd;
}


static int refresh_qsfp_cache(int fd, uint8_t addr, uint8_t reg, uint8_t *buffer, int len)
{
    if (fd < 0) {
        return -1;
    }
    int ret = -1;
    int regAddr = reg;
    unsigned char dataBuff[QSFP_PAGESIZE] = { 0 };
    unsigned short dataLen = QSFP_PAGESIZE;
    //读数据有2个msg
    struct i2c_msg msg[2] = {
        {
            .addr = addr,   //设备地址
            .flags = 0,         //标志，为0表示写数据
            .len = 1,           //要写的数据的长度
            .buf = (__u8 *)&regAddr,   //要写的数据的地址
        },
        {
            .addr = addr,   //设备地址
            .flags = I2C_M_RD,  //标志，I2C_M_RD表示主机向主机读数据
            .len = dataLen,         //要读取的数据的长度
            .buf = dataBuff,        //读取的数据存放的地址
        },
    };

    struct i2c_rdwr_ioctl_data rdwr_msg = {
        .msgs = msg,
        .nmsgs = 2,
    };

    ret = ioctl(fd, I2C_RDWR, &rdwr_msg);
    if (ret < 0) {
      printf("refresh_qsfp_cache failed, errno=%d.\n", errno);
      return ret;
    }
    memcpy(buffer,dataBuff,len);
    
    return ret;
}


static int qsfp_write(int fd,uint8_t addr, uint8_t reg,uint8_t *wdata, uint8_t wlen)
{
    if (fd < 0) {
        return -1;
    }
    int ret = -1;
    unsigned char buff[20] = { 0 };
    unsigned short dataLen = (unsigned short)(wlen+1);
    buff[0] = reg;
    memcpy(&buff[1], wdata, wlen);

    //写数据是1个msg
    struct i2c_msg msg = {
        .addr = addr,
        .flags = 0,
        .len = dataLen,
        .buf = buff,
    };

    struct i2c_rdwr_ioctl_data rdwr_msg = {
        .msgs = &msg,
        .nmsgs = 1,
    };

    ret = ioctl(fd, I2C_RDWR, &rdwr_msg);

    return ret;
}


static int qsfp_read(int fd, unsigned short dev_addr,  unsigned char reg_addr, unsigned char* data, unsigned int len)
{
    int ret = -1;
    unsigned short dataLen = (unsigned short)len;
    //读数据有2个msg
    struct i2c_msg msg[2] = {
        {
            .addr = dev_addr,   //设备地址
            .flags = 0,         //标志，为0表示写数据
            .len = 1,           //要写的数据的长度
            .buf = &reg_addr,   //要写的数据的地址
        },
        {
            .addr = dev_addr,   //设备地址
            .flags = I2C_M_RD,  //标志，I2C_M_RD表示主机向主机读数据
            .len = dataLen,         //要读取的数据的长度
            .buf = data,        //读取的数据存放的地址
        },
    };

    struct i2c_rdwr_ioctl_data rdwr_msg = {
        .msgs = msg,
        .nmsgs = 2,
    };

    ret = ioctl(fd, I2C_RDWR, &rdwr_msg);

    return ret;
}

int qsfp_4x_init()
{
    m_qsfp_4x_fd = qsfp_init(X4_DEV_NAME);
    if(m_qsfp_4x_fd < 0) {
        return -1;
    }
    return 1;
}

int qsfp_12x_init()
{
    m_qsfp_12x_fd = qsfp_init(X12_DEV_NAME);
    if(m_qsfp_12x_fd < 0) {
        return -1;
    }
    return 1;
}

int refresh_qsfp_4x_cache(struct qsfp_4x_cache *cp)
{
    return refresh_qsfp_cache(m_qsfp_4x_fd,QSFP_DEV,0,(uint8_t *)cp,QSFP_PAGESIZE);
}


int refresh_qsfp_12x_tx_cache(struct qsfp_12x_Txcache *cp)
{
    return refresh_qsfp_cache(m_qsfp_12x_fd,QSFP_TX_DEV,0,(uint8_t *)cp,QSFP_PAGESIZE);
}

int refresh_qsfp_12x_rx_cache(struct qsfp_12x_Rxcache *cp)
{
    return refresh_qsfp_cache(m_qsfp_12x_fd,QSFP_RX_DEV,0,(uint8_t *)cp,QSFP_PAGESIZE);
}


int qsfp_page_4x_change(int page)
{
    return qsfp_write(m_qsfp_4x_fd,QSFP_DEV,QSFP_PAGE, (uint8_t *)&page,1);
}

int qsfp_page_12x_tx_change(int page)
{
    return qsfp_write(m_qsfp_12x_fd,QSFP_TX_DEV,QSFP_PAGE, (uint8_t *)&page,1);
}

int qsfp_page_12x_rx_change(int page)
{
    return qsfp_write(m_qsfp_12x_fd,QSFP_RX_DEV,QSFP_PAGE, (uint8_t *)&page,1);
}

void refresh_qsfp_4x_upperMemory()
{
    for(int i=0;i<QSFP_PAGENUM_4X;i++)
    {
        qsfp_page_4x_change(i);
        refresh_qsfp_cache(m_qsfp_4x_fd,QSFP_DEV,(QSFP_PAGE+1),(uint8_t *)m_qsfp_4x_upper[i],QSFP_PAGEUPPER);
    }
    qsfp_page_4x_change(0); //恢复第一页
}

void refresh_qsfp_12x_tx_upperMemory()
{
    for(int i=0;i<QSFP_PAGENUM_12X;i++)
    {
        qsfp_page_12x_tx_change(i);
        refresh_qsfp_cache(m_qsfp_12x_fd,QSFP_TX_DEV,(QSFP_PAGE+1),(uint8_t *)m_qsfp_12x_tx_upper[i],QSFP_PAGEUPPER);
    }
}

void refresh_qsfp_12x_rx_upperMemory()
{
    for(int i=0;i<QSFP_PAGENUM_12X;i++)
    {
        qsfp_page_12x_rx_change(i);
        refresh_qsfp_cache(m_qsfp_12x_fd,QSFP_RX_DEV,(QSFP_PAGE+1),(uint8_t *)m_qsfp_12x_rx_upper[i],QSFP_PAGEUPPER);
    }
}



// static int m_qsfpFd = -1;

// bool qsfpOpen(const char* filename)
// {
//     m_qsfpFd = i2cInit(filename);    //初始化I2C设备
//     if (m_qsfpFd < 0) {
//         qlog_e("qsfp open failed..");
//         return false;
//     }
//     return true;
// }

void qsfpClose()
{
    close(m_qsfp_4x_fd);
    close(m_qsfp_12x_fd);
}

int qsfp_4x_check()
{
    int ret = 0;
    unsigned char g_ucReg = 0x0,data = 0;
    
    int res = qsfp_read(m_qsfp_4x_fd,QSFP_DEV,g_ucReg,&data,1);
    
    if (res < 0) {
    	 qlog_e("读qsfp光模块失败.\n");
    } else {

        qlog_w("读到光模块ID:%x.\n",data);
		if(data == 0x0d ) {
			ret = 1;
		}
    }
    return ret;
}

#define POWER_CFG 93
int qsfp_power()
{
    int ret=0;
    unsigned char page = 0x01,data = 0;
    qsfp_write(m_qsfp_4x_fd,QSFP_DEV, POWER_CFG,&page, 1);
    
    usleep(10);
    int res = qsfp_read(m_qsfp_4x_fd,QSFP_DEV,POWER_CFG,&data,1);
    if (res < 0) {
    	qlog_e("Error qsfp config power.\n");
    } else {
    	qlog_w("Read qsfp power:%x.\n",data);
		if (page == data) {
			ret = 1;
		}

    }
    return ret;
}

// 在 Qsfp.cpp 文件顶部添加以下实现（或放在公共工具模块中）
static void filter_string(uint8_t* str) {
    if (!str) return;
    // 示例：将字符串中的非可打印字符替换为 '\0' 或空格
    for (int i = 0; str[i] != '\0'; ++i) {
        if (str[i] < 32 || str[i] > 126) {  // 非可打印字符范围
            str[i] = '\0';  // 或者设置为空格 ' '
        }
    }
}

void qsfpGetStatus(struct qsfpUpdate &m_qsfpUpdate) 
{
    uint16_t val = 0;
    struct qsfp_4x_cache m_x4Cache;
    struct upperMemory00h m_upperMemory00h;
    
    memset(&m_x4Cache,0,sizeof(m_x4Cache));
    refresh_qsfp_4x_cache(&m_x4Cache);//获取第0页数据到m_x4Cache缓存里
    refresh_qsfp_4x_upperMemory();//获取后续分页数据到m_qsfp_4x_upper缓存里

    memcpy((uint8_t *)&m_upperMemory00h,m_qsfp_4x_upper[0],sizeof(m_upperMemory00h));



    val = (uint16_t)( m_x4Cache.m_inRx1Power[0] << 8 ) | m_x4Cache.m_inRx1Power[1];
    m_qsfpUpdate.m_inRx1Power = convertPower(val);

    val = (uint16_t)( m_x4Cache.m_inRx2Power[0] << 8 ) | m_x4Cache.m_inRx2Power[1];
    m_qsfpUpdate.m_inRx2Power = convertPower(val);

    val = (uint16_t)( m_x4Cache.m_inRx3Power[0] << 8 ) | m_x4Cache.m_inRx3Power[1];
    m_qsfpUpdate.m_inRx3Power = convertPower(val);

    val = (uint16_t)( m_x4Cache.m_inRx4Power[0] << 8 ) | m_x4Cache.m_inRx4Power[1];
    m_qsfpUpdate.m_inRx4Power = convertPower(val);

    val = (uint16_t)( m_x4Cache.m_inTx1Power[0] << 8 ) | m_x4Cache.m_inTx1Power[1];
    m_qsfpUpdate.m_inTx1Power = convertPower(val);

    val = (uint16_t)( m_x4Cache.m_inTx2Power[0] << 8 ) | m_x4Cache.m_inTx2Power[1];
    m_qsfpUpdate.m_inTx2Power = convertPower(val);

    val = (uint16_t)( m_x4Cache.m_inTx3Power[0] << 8 ) | m_x4Cache.m_inTx3Power[1];
    m_qsfpUpdate.m_inTx3Power = convertPower(val);

    val = (uint16_t)( m_x4Cache.m_inTx4Power[0] << 8 ) | m_x4Cache.m_inTx4Power[1];
    m_qsfpUpdate.m_inTx4Power = convertPower(val);

    val = (uint16_t)( m_x4Cache.m_inTx1Bias[0] << 8 ) | m_x4Cache.m_inTx1Bias[1];
    
    m_qsfpUpdate.m_inTx1Bias = convertBiasCurrent(val);
    val = (uint16_t)( m_x4Cache.m_inTx2Bias[0] << 8 ) | m_x4Cache.m_inTx2Bias[1];
    m_qsfpUpdate.m_inTx2Bias = convertBiasCurrent(val);

    val = (uint16_t)( m_x4Cache.m_inTx3Bias[0] << 8 ) | m_x4Cache.m_inTx3Bias[1];
    m_qsfpUpdate.m_inTx3Bias = convertBiasCurrent(val);

    val = (uint16_t)( m_x4Cache.m_inTx4Bias[0] << 8 ) | m_x4Cache.m_inTx4Bias[1];
    m_qsfpUpdate.m_inTx4Bias = convertBiasCurrent(val);
    
    uint16_t temp = (uint16_t)( m_x4Cache.m_inTemp[0] << 8 ) | m_x4Cache.m_inTemp[1];
    uint16_t temp1 = (uint16_t)( m_x4Cache.m_inVoltage[0] << 8 ) | m_x4Cache.m_inVoltage[1];

    m_qsfpUpdate.m_monitorTemp1 = convertTemperature(temp);
    m_qsfpUpdate.m_monitorVcc1 = convertVoltage(temp1);

    // 对成员字符串进行处理
    filter_string(m_upperMemory00h.m_vendorName);
    filter_string(m_upperMemory00h.m_vendorPN);
    filter_string(m_upperMemory00h.m_vendorRev);
    filter_string(m_upperMemory00h.m_vendorSN);

    if(0) {
        qlog_n("************分割线***QSFP数据传输状态信息*********\n");
        qlog_n("4x Device Tech:%d\n",m_upperMemory00h.m_devTech);
        qlog_n("4x Vendor name:%s\n",m_upperMemory00h.m_vendorName);
        qlog_n("4x Vendor PN:%s\n",m_upperMemory00h.m_vendorPN);
        qlog_n("4x Vendor Rev:%s\n",m_upperMemory00h.m_vendorRev);
        uint16_t wavelength = (uint16_t)((uint16_t)m_upperMemory00h.m_waveLength[0] << 8 | m_upperMemory00h.m_waveLength[1]);
        qlog_n("4x Wavelength:%d nm\n",(wavelength/20));
        qlog_n("4x Vendor SN:%s\n",m_upperMemory00h.m_vendorSN);
        qlog_n("4x 数据准备标志位:%d,监控数据未准备就绪.位保持高,直到数据准备好被读取,置低\n",m_x4Cache.m_byte2.byte2.data_not_ready);
        qlog_n("4x RX1通道功率:%fmW\n",m_qsfpUpdate.m_inRx1Power);
        qlog_n("4x RX2通道功率:%fmW\n",m_qsfpUpdate.m_inRx2Power);
        qlog_n("4x RX3通道功率:%fmW\n",m_qsfpUpdate.m_inRx3Power);
        qlog_n("4x RX4通道功率:%fmW\n",m_qsfpUpdate.m_inRx4Power);
        qlog_n("4x TX1通道功率:%fmW\n",m_qsfpUpdate.m_inTx1Power);
        qlog_n("4x TX2通道功率:%fmW\n",m_qsfpUpdate.m_inTx2Power);
        qlog_n("4x TX3通道功率:%fmW\n",m_qsfpUpdate.m_inTx3Power);
        qlog_n("4x TX4通道功率:%fmW\n",m_qsfpUpdate.m_inTx4Power);
        qlog_n("4x TX1通道偏置电流:%fmA\n",m_qsfpUpdate.m_inTx1Bias);
        qlog_n("4x TX2通道偏置电流:%fmA\n",m_qsfpUpdate.m_inTx2Bias);
        qlog_n("4x TX3通道偏置电流:%fmA\n",m_qsfpUpdate.m_inTx3Bias);
        qlog_n("4x TX4通道偏置电流:%fmA\n",m_qsfpUpdate.m_inTx4Bias);
        printMonitor(temp,temp1);
        qlog_n("************分割线***QSFP数据传输状态信息*********\n");
    }


}